#pragma once
#include "common.h"
#include "trace.h"
#include "config.h"
#include "counter.h"

class CacheLineReplacer
{
public:
    virtual int replace(word_t addr) = 0;
};

class RandomReplacer : public CacheLineReplacer
{
private:
    int way;

public:
    RandomReplacer(int way) : way(way)
    {
    }
    int replace(word_t addr) override
    {
        uint32_t i = rand() % way;
        return i;
    }
};

class NaiveCache
{
public:
    virtual void reset() = 0;
    virtual bool send(OP *op) = 0;
    virtual bool recv(OP *op) = 0;
    virtual void run() = 0;
};

class PerfectCache : public NaiveCache
{
public:
    PerfectCache() {}
    ~PerfectCache() {}
    void reset() override {}
    bool send(OP *op) override { return true; }
    bool recv(OP *op) override { return true; }
    void run() override {}
};

class NormalNaiveCache : public NaiveCache
{
public:
    typedef std::tuple<OP *, uint64_t> MSHR;
    std::vector<MSHR> mshrs;
    uint64_t cycle = 0;
    NormalNaiveCache();
    ~NormalNaiveCache();
    void reset() override;
    bool send(OP *op) override;
    bool recv(OP *op) override;
    void run() override;
};
